﻿/**
 *	@author	Valentyn Derkach
 *
 *	2008.05.11
 *	- added toggle property
 */

package com.bizmlib.ui.composite
{
	import flash.events.*;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	
	import com.bizmlib.ui.composite.UICompositionEvent;
	import com.bizmlib.utils.sets.*;
	import com.bizmlib.utils.array.ArrayHandling;
	
	
	[Event(name="itemSelect", type="com.bizmlib.ui.composite.UICompositionEvent")]
	[Event(name="hideComplete", type="com.bizmlib.ui.composite.UICompositionEvent")]
	[Event(name="itemsRearrange", type="com.bizmlib.ui.composite.UICompositionEvent")]
	
	
	public class UIComposition extends MovieClip implements IUICompositeItem
	{
		private static const TOGGLE_VALUE_DEFAULT:Boolean = true;
		
		static protected var STATE_NONE:Number = 0;
		static protected var STATE_INIT:Number = 1;
		static protected var STATE_SHOW:Number = 2;
		static protected var STATE_HIDE:Number = 4;
		static protected var STATE_CLEAN:Number = 5;
		static protected var STATE_INPROGRESS:Number = 6;
		static protected var STATE_DONE:Number = 7;
		
		protected var itemClass:Class = UICompositionItem;
	
		protected var state:Number = STATE_INIT;
		protected var stateShow:Number;
		protected var stateHide:Number;
		
		protected var __dataProvider:Array;
		private var dataProviderCopy:Array;
		protected var menuManager:SetManager;
		protected var itemsCount:Number = 0;
		
		private var __toggle:Boolean;
		private var lockArrangeItemsCall:Boolean;
		
		/**
		 * itemsList is a list of the items that fits the current dataProvder(data property), visibleItemsList is a list of all present items i.e. includes the items that has to be removed.
		 * This is a weak point of the whole class. Check the addItem, removeItem and moveItem methods, check how i handle the indexes of these lists and you'll get what i mean.
		 */
		protected var itemsList:Array;
		protected var visibleItemsList:Array;
		
		protected var itemsManager:UICompositeManager;
		protected var __selectedItem:MovieClip = undefined;
		protected var __selectedIndex:Number;
		public var stopItemEventsBubbling:Boolean;
		public var dispatchBubblingEvents:Boolean;
		protected var hideReversed:Boolean;
		protected var dispatchItemsRearrangeEventWhenEmpty:Boolean;
	
	
		public function UIComposition()
		{
			init();
			createChildren();
		}
	
	
	
		// GETTERS/SETTER ═════════════════════════════════════════════════════════════════════════════════════════════
		public function set dataProvider(value:Array):void
		{
			//trace(this + ".dataProvider (set) " + arguments);
			
			if(state==STATE_INIT)
			{
				__dataProvider = value;
			}
			else if(state==STATE_CLEAN)
			{
				return;
			}
			else
			{
				lockArrangeItemsCall = true;
				
				beforeUpdate(dataProvider);
				//var localPrevData:Array = dataProvider;
				__dataProvider = value;
				
				var currentDataProvider:Array = dataProvider || new Array();
				invokeManagerParsing(dataProvider, /**localPrevData/**/dataProviderCopy);
				
				dataProviderCopy = currentDataProvider.concat();
				
				if(state==STATE_SHOW)
				{
					doShowItems();
				}
				afterUpdate();
				
				lockArrangeItemsCall = false;
				arrangeItems(0, itemsList[0] as DisplayObject);
			}

		}
		public function get dataProvider():Array
		{
			return __dataProvider;
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		public function get numItems():Number
		{
			return itemsList.length;
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		/**
		 * Sets the toggle mode (on/off) for the UIComposition and all its items.
		 */
		public function set toggle(value:Boolean):void
		{
			//trace(this + ".toggle (set) " + value);
			
			__toggle = value;
			
			for each(var itemMC:MovieClip in itemsList)
			{
				(itemMC as UICompositionItem).toggle = toggle;
			}
		}
		public function get toggle():Boolean
		{
			return __toggle;
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		public function get selectedItem():MovieClip
		{
			return __selectedItem;
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		public function set selectedIndex(value:Number):void
		{
			if(selectedIndex==value)
			{
				return;
			}
			setSelectedIndex(value, true);
		}
		public function get selectedIndex():Number
		{
			return __selectedIndex;
		}
		//═════════════════════════════════════════════════════════════════════════════════════════════════════════════
	
	
	
		// PUBLIC METHODS ═════════════════════════════════════════════════════════════════════════════════════════════
		public function show():Boolean
		{
			//trace(this + ".show(" + arguments + ")");
			//trace("state=" + state);
			
			if(state==STATE_INIT || state==STATE_CLEAN || !beforeShow())
			{
				return false;
			}
			
			state = STATE_SHOW;
			stateShow = STATE_INPROGRESS;
			stateHide = STATE_NONE;
			preselectItemOnShow();
			doShowItems();
			
			dispatchEvent(new UICompositionEvent(UICompositionEvent.SHOW_START));
			
			return true;
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		public function hide():Boolean
		{
			//trace(this + ".hide()");
			//trace("state=" + state);
	
			switch(state){
				case STATE_INIT:
				case STATE_CLEAN:
					return false;
					break;
				default:
					state = STATE_HIDE;
					stateShow = STATE_NONE;
					stateHide = STATE_INPROGRESS;
					doHideItems();
					
					dispatchEvent(new UICompositionEvent(UICompositionEvent.HIDE_START));
					
					break;
			}
			return true;
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		public function clear():void
		{
			//trace(this + ".clear()");
			while(itemsList.length>0)
			{
				removeItem(itemsList.length-1);
			}
			dataProvider = undefined;
			setSelectedItem(undefined);
			setSelectedIndex(Number.NaN, false);
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		public function clean():void
		{
			state = STATE_CLEAN;
			stateShow = STATE_NONE;
			stateHide = STATE_NONE;
			
			while(itemsList.length>0)
			{
				removeItem(itemsList.length-1, true);
			}
			
			clear();
			
			cleanItemsManager();
			cleanMenuManager();
			
			itemsList = null;
			visibleItemsList = null;
			setSelectedItem(null);
			setSelectedIndex(Number.NaN, false);
			dataProviderCopy = null;
			itemClass = null;
			
			afterClean();
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		public function getItemByDataProvider(dataProvider:Object):DisplayObject
		{
			for(var i:Number=0; i<visibleItemsList.length; i++)
			{
				if(visibleItemsList[i].dataProvider==dataProvider)
				{
					return visibleItemsList[i] as DisplayObject;
				}
			}
			
			return null;
		}
		public function getItemIndex(item:DisplayObject):int
		{
			for(var i:int=0; i<visibleItemsList.length; i++)
			{
				if(visibleItemsList[i]==item)
				{
					return i;
				}
			}
			
			return -1;
		}
		//═════════════════════════════════════════════════════════════════════════════════════════════════════════════
	
	
	
		// protected METHODS ════════════════════════════════════════════════════════════════════════════════════════════
		protected function init():void
		{
			stopItemEventsBubbling = false;
			
			itemsList = new Array();
			visibleItemsList = new Array();
			toggle = TOGGLE_VALUE_DEFAULT;
			
			dataProviderCopy = null;
			
			/**
			var toggleAsObject:Object = toggle;
			if(toggleAsObject==undefined || toggleAsObject==null)
			{
				toggle = TOGGLE_VALUE_DEFAULT;
			}
			/**/
			
			createMenuManager();
			subscribeToManagersEvents();
			createItemsManager();
			subscribeToItemsManagerEvents();
			afterInit();
			
			state = STATE_HIDE;
			stateShow = STATE_NONE;
			stateHide = STATE_DONE;
			if(dataProvider)
			{
				var localDataCopy:Array = dataProvider;
				__dataProvider = undefined;
				dataProvider = localDataCopy;
			}
		}
		protected function afterInit():void
		{
		}
		protected function createChildren():void
		{
		}
		protected function beforeUpdate(newData:Array):void
		{
		}
		protected function afterUpdate():void
		{
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		protected function preselectItemOnShow():void
		{
			//trace(this + ".preselectItemOnShow()");
			//if(selectedItem===undefined)
			if(!selectedItem && itemsList.length>0 && toggle)
			{
				itemPressed(itemsList[0].index, itemsList[0], false);
			}
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		protected function createItemsManager():void
		{
			itemsManager = new UIQueueManager();
		}
		protected function subscribeToItemsManagerEvents():void
		{
			itemsManager.addEventListener(UICompositeManagerEvent.SHOW_COMPLETE, showCompleted);
			itemsManager.addEventListener(UICompositeManagerEvent.HIDE_COMPLETE, hideCompleted);
			itemsManager.addEventListener(UICompositeManagerEvent.ITEMS_REMOVED, itemsRemoved);
		}
		protected function cleanItemsManager():void
		{
			itemsManager.removeEventListener(UICompositeManagerEvent.SHOW_COMPLETE, showCompleted);
			itemsManager.removeEventListener(UICompositeManagerEvent.HIDE_COMPLETE, hideCompleted);
			itemsManager.removeEventListener(UICompositeManagerEvent.ITEMS_REMOVED, itemsRemoved);
			
			itemsManager = null;
		}
		protected function createMenuManager():void
		{
			menuManager = new SetManagerFlatOrderedList();
		}
		protected function subscribeToManagersEvents():void
		{
			menuManager.addEventListener(SetManagerEvent.ITEM_ADD, addItemEventHandling);
			menuManager.addEventListener(SetManagerEvent.ITEM_REMOVE, removeItemEventHandling);
			menuManager.addEventListener(SetManagerEvent.ITEM_UPDATE, updateItemEventHandling);
			menuManager.addEventListener(SetManagerEvent.ITEM_MOVE, moveItemEventHandling);
		}
		protected function invokeManagerParsing(newData:Object, previousData:Object):void
		{
			//trace(this + ".invokeManagerParsing(" + arguments + ")");
			//trace("newData=" + newData);
			//trace("previousData=" + previousData);
			
			menuManager.parseArray(newData as Array, previousData as Array);
		}
		protected function cleanMenuManager():void
		{
			menuManager.removeEventListener(SetManagerEvent.ITEM_ADD, addItemEventHandling);
			menuManager.removeEventListener(SetManagerEvent.ITEM_REMOVE, removeItemEventHandling);
			menuManager.removeEventListener(SetManagerEvent.ITEM_UPDATE, updateItemEventHandling);
			menuManager.removeEventListener(SetManagerEvent.ITEM_MOVE, moveItemEventHandling);
			
			menuManager = null;
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		protected function afterVisibleItemsListUpdate():void
		{
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		protected function addItemEventHandling(event:SetManagerEvent):void
		{
			addItem(event.itemData, event.newItemIndex);
		}
		protected function addItem(itemData:Object, itemIndex:Number, itemProperties:Object = undefined, containerMC:MovieClip = undefined):DisplayObject
		{
			//trace(this + ".addItem(" + arguments + ")");
	
			itemProperties = itemProperties || new Object();
			itemProperties.index = itemIndex;
			itemProperties.dataProvider = itemData;
			itemProperties.toggle = toggle;
			
			containerMC = containerMC || this;
			//var localNewItem:MovieClip = containerMC.attachMovie(linkageIDMenuItem, "Item" + itemsCount, depth, itemProperties);
			
			//trace("itemClass=" + itemClass);
			/**
			var localNewItemAbstract:Object = new itemClass();
			//trace("localNewItemAbstract=" + localNewItemAbstract);
			/**/
			var localNewItem:IUICompositionItem = (new itemClass()) as IUICompositionItem;
			//trace("localNewItem=" + localNewItem);
			var localNewItemAsDisplayObject:DisplayObject = localNewItem as DisplayObject;
			//trace("localNewItemAsDisplayObject=" + localNewItemAsDisplayObject);
			
			localNewItem.addEventListener(UICompositionItemEvent.PRESS,			itemPressHandler);
			localNewItem.addEventListener(UICompositionItemEvent.RELEASE,			itemReleaseHandler);
			localNewItem.addEventListener(UICompositionItemEvent.RESIZE, 			itemResizeHandler);
			localNewItem.addEventListener(UICompositionItemEvent.DRAG_INVOKED, 	itemDragInvokedHandler);
			
			containerMC.addChild(localNewItemAsDisplayObject);
			
			if(itemProperties && (itemProperties is Object))
			{
				for(var propertyName:String in itemProperties)
				{
					localNewItemAsDisplayObject[propertyName] = itemProperties[propertyName];
				}
			}
			
			itemsList = (itemsList.slice(0, itemIndex)).concat(localNewItem, itemsList.slice(itemIndex));
			for(var i:Number=itemIndex+1; i<itemsList.length; i++)
			{
				itemsList[i].index = i;
			}
			updateSelectedIndex();
			
			var visibleListIndex:Number = 0;
			if(itemIndex == itemsList.length - 1)
			{
				visibleListIndex = visibleItemsList.length;
			}
			else
			{
				visibleListIndex = ArrayHandling.getItemIndex(visibleItemsList, itemsList[itemIndex+1]);
			}
			visibleItemsList = (visibleItemsList.slice(0, visibleListIndex)).concat(localNewItem, visibleItemsList.slice(visibleListIndex));
			afterVisibleItemsListUpdate();
			//trace("visibleItemsList=" + visibleItemsList);
			itemsCount++;
			
			dispatchEvent(new UICompositionEvent(UICompositionEvent.ITEM_ADDED, itemData, localNewItemAsDisplayObject, undefined, dispatchBubblingEvents));
			
			return localNewItemAsDisplayObject;
		}
		protected function removeItemEventHandling(event:SetManagerEvent):void
		{
			removeItem(event.currentItemIndex);
		}
		protected function removeItem(itemIndex:Number, removeImmediatelly:Boolean = false):void
		{
			//trace(this + ".removeItem(" + arguments + ")");
			
			removeImmediatelly = removeImmediatelly || false;
			
			var localNewSelectedItem:MovieClip = null;
			if(selectedItem==itemsList[itemIndex] && toggle && state!=STATE_CLEAN)
			{
				localNewSelectedItem = (itemsList[itemIndex+1] || itemsList[itemIndex-1]) || undefined;
			}
			
			setSelectedIndex(localNewSelectedItem ? localNewSelectedItem.index : undefined);
			
			var itemToRemove:IUICompositionItem = itemsList[itemIndex] as IUICompositionItem;
			itemsList = (itemsList.slice(0, itemIndex)).concat(itemsList.slice(itemIndex+1));
			
			if(removeImmediatelly)
			{
				var visibleListIndex:Number = ArrayHandling.getItemIndex(visibleItemsList, itemToRemove);
				visibleItemsList = (visibleItemsList.slice(0, visibleListIndex)).concat(visibleItemsList.slice(visibleListIndex+1));
				afterVisibleItemsListUpdate();
				//itemToRemove.remove();
				removeItemFinally(itemToRemove);
			}
			else
			{
				itemsManager.remove([itemToRemove]);
			}
			
			for(var i:Number=itemIndex; i<itemsList.length; i++)
			{
				itemsList[i].index = i;
			}
		}
		protected function removeItemFinally(item:IUICompositionItem):void
		{
			item.remove();
			
			item.removeEventListener(UICompositionItemEvent.PRESS,			itemPressHandler);
			item.removeEventListener(UICompositionItemEvent.RELEASE,			itemReleaseHandler);
			item.removeEventListener(UICompositionItemEvent.RESIZE, 			itemResizeHandler);
			item.removeEventListener(UICompositionItemEvent.DRAG_INVOKED, 	itemDragInvokedHandler);
			
			var itemAsDisplayObject:DisplayObject = item as DisplayObject;
			if(itemAsDisplayObject.parent)
			{
				itemAsDisplayObject.parent.removeChild(itemAsDisplayObject);
			}
			itemAsDisplayObject = null;
			
			var itemAsObject:Object = item as Object;
			itemAsObject.dataProvider = null;
			itemAsObject = null;
			
			item = null;
		}
		protected function updateItemEventHandling(event:SetManagerEvent):void
		{
			updateItem(event.itemData, event.currentItemIndex);
		}
		protected function updateItem(itemData:Object, itemIndex:Number):void
		{
			//trace(this + ".updateItem(" + arguments + ")");
			//trace("itemsList=" + itemsList);
			//trace(itemsList[itemIndex]);
			
			if(itemsList[itemIndex])
			{
				itemsList[itemIndex].dataProvider = itemData;
			}
		}
		protected function moveItemEventHandling(event:SetManagerEvent):void
		{
			moveItem(event.itemData, event.currentItemIndex, event.newItemIndex);
		}
		protected function moveItem(itemData:Object, itemIndex:Number, newItemIndex:Number):Boolean
		{
			//trace(this + ".moveItem(" + arguments + ")");
			
			if(itemsList[newItemIndex].dataProvider == itemData)
			{
				return false;
			}
			
			var visibleListIndex1:Number = ArrayHandling.getItemIndex(visibleItemsList, itemsList[itemIndex]);
			var visibleListIndex2:Number = ArrayHandling.getItemIndex(visibleItemsList, itemsList[newItemIndex]);
			//trace("visibleListIndex1:" + visibleListIndex1 + "\tvisibleListIndex2:" + visibleListIndex2);
			
			var localBuffer:Object = itemsList[itemIndex];
			itemsList[itemIndex] = itemsList[newItemIndex];
			itemsList[newItemIndex] = localBuffer;
			itemsList[itemIndex].index = itemIndex;
			itemsList[newItemIndex].index = newItemIndex;
			
			updateSelectedIndex();
			
			localBuffer = visibleItemsList[visibleListIndex1];
			visibleItemsList[visibleListIndex1] = visibleItemsList[visibleListIndex2];
			visibleItemsList[visibleListIndex2] = localBuffer;
			afterVisibleItemsListUpdate();
			
			//trace("itemsList=" + itemsList);
			
			return true;
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		protected function itemsRemoved(event:UICompositeManagerEvent):void
		{
			//trace(this + ".itemRemoved(" + arguments + ")");
			
			var removedItems:Array = event.items;
			var itemIndex:Number = -1;
			
			for(var i:Number=0; i<removedItems.length; i++)
			{
				if((itemIndex = ArrayHandling.getItemIndex(visibleItemsList, removedItems[i])) > -1)
				{
					var localRemovedVisibleItems:Array = visibleItemsList.splice(itemIndex, 1);
					afterVisibleItemsListUpdate();
					var removedItem:IUICompositionItem = (localRemovedVisibleItems[0] as IUICompositionItem);
					
					//removedItem.remove();
					removeItemFinally(removedItem);
					
					localRemovedVisibleItems = null;
				}
			}
			
			arrangeItems();
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		protected function itemPressHandler(event:UICompositionItemEvent):void
		{
			if(stopItemEventsBubbling)
			{
				event.stopImmediatePropagation();
			}
			
			var index:Number = event.target.index;
			var target:MovieClip = event.target as MovieClip;
			itemPressed(index, target, false);
			//itemPressed(eventObject.target.index, eventObject.target, false);
		}
		protected function itemPressed(itemIndex:Number, itemMC:MovieClip, noEvent:Boolean = false):Boolean
		{
			//trace(this + ".itemPressed(" + arguments + ")");
			
			noEvent = noEvent || false;
			
			if(selectedItem!=itemMC)
			{
				switchSelection(itemMC);
				//return false;
			}
			//trace("noEvent=" + noEvent + "\tselectedItem=" + selectedItem);
			if(!noEvent && ((selectedItem && toggle) || (itemMC && !toggle)))
			{
				var item:MovieClip = selectedItem || itemMC;
				selectItem(item.index, item);
			}
			
			return true;
		}
		protected function switchSelection(itemMC:MovieClip, doRelease:Boolean = true, doPress:Boolean = true):void
		{
			//trace(this + ".sitchSelection(" + arguments + ")");
			//trace("selectedItem=" + selectedItem);
			
			if(selectedItem)
			{
				var localSelectedItemCopy:MovieClip = selectedItem;
				setSelectedItem(undefined);
				setSelectedIndex(Number.NaN, false);
				if(doRelease)
				{
					localSelectedItemCopy.release(true);
				}
			}
			if(itemMC && toggle)
			{
				setSelectedItem(itemMC);
				setSelectedIndex(itemMC.index, false);
				if(doPress)
				{
					selectedItem.press(true);
				}
			}
		}
		protected function setSelectedItem(itemMC:MovieClip = undefined):void
		{
			__selectedItem = itemMC;
		}
		protected function selectItem(itemIndex:Number, itemMC:MovieClip):void
		{
			//trace(this + ".selectItem(" + arguments + ")");
			
			dispatchEvent(new UICompositionEvent(UICompositionEvent.ITEM_SELECT, itemMC.dataProvider, itemMC, itemIndex, dispatchBubblingEvents));
		}
		protected function setSelectedIndex(index:Number = undefined, handleSelectionChange:Boolean = true):void
		{
			__selectedIndex = index;
			if(!handleSelectionChange)
			{
				return;
			}
			else if(!isNaN(index))
			{
				for(var i:Number=0; i<visibleItemsList.length; i++)
				{
					if(visibleItemsList[i].index==selectedIndex)
					{
						switchSelection(visibleItemsList[i]);
						return;
					}
				}
			}
			switchSelection(undefined);
		}
		protected function updateSelectedIndex():void
		{
			setSelectedIndex(selectedItem ? selectedItem.index : Number.NaN, false);
		}
		protected function itemReleaseHandler(event:UICompositionItemEvent):void
		{
			if(stopItemEventsBubbling)
			{
				event.stopImmediatePropagation();
			}
			
			itemReleased(event.target.index, event.target as MovieClip);
		}
		protected function itemReleased(itemIndex:Number, itemMC:MovieClip):void
		{
			//trace(this + ".itemReleased(" + arguments + ")");
			itemPressed(undefined, undefined, true);
		}
		protected function itemResizeHandler(event:UICompositionItemEvent):void
		{
			//trace(this + ".itemResizeHandler(" + arguments + ")");
			//trace("stopItemEventsBubbling=" + stopItemEventsBubbling);
			
			if(stopItemEventsBubbling)
			{
				event.stopImmediatePropagation();
			}
			
			var item:UICompositionItem = event.item;
			//trace("item=" + item);
			if(item)
			{
				arrangeItems(item.index, item);
			}
		}
		protected function itemDragInvokedHandler(event:UICompositionItemEvent):void
		{
			var item:UICompositionItem = event.item;
			
			event.stopImmediatePropagation();
			
			dispatchEvent(new UICompositionItemEvent(event.type, event.item, false));
			/**
			if(stopItemEventsBubbling)
			{
				event.stopImmediatePropagation();
				//event.stopPropagation();
			}
			/**/
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		protected function beforeShow():Boolean
		{
			return true;
		}
		protected function doShowItems():void
		{
			//trace(this + ".doShowItems(" + arguments + ")");
			//trace("state=" + state);
			//trace("itemsList=" + itemsList);
			
			itemsManager.show(itemsList, true);
		}
		protected function showCompleted(event:UICompositeManagerEvent):void
		{
			//trace(this + ".showCompleted(" + arguments + ")");
			
			stateShow = STATE_DONE;
			dispatchEvent(new UICompositionEvent(UICompositionEvent.SHOW_COMPLETE, undefined, undefined, undefined, dispatchBubblingEvents));
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		protected function beforeItemsHide():void
		{
			//if(selectedItem!=undefined)
			if(selectedItem)
			{
				setSelectedIndex(Number.NaN, false);
				setSelectedItem(null);
			}
		}
		protected function doHideItems():void
		{
			var itemsListCopy:Array = itemsList.concat();
			if(hideReversed)
			{
				itemsListCopy = itemsListCopy.reverse();
			}
			itemsManager.hide(itemsListCopy);
		}
		protected function hideCompleted(event:UICompositeManagerEvent):void
		{
			//trace(this + ".hideCompleted()");
			
			stateHide = STATE_DONE;
			dispatchEvent(new UICompositionEvent(UICompositionEvent.HIDE_COMPLETE, undefined, undefined, undefined, dispatchBubblingEvents));
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		protected function afterClean():void
		{
		}
		//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
		protected function arrangeItems(itemIndex:Number = undefined, item:DisplayObject = undefined, extra:Object = undefined):void
		{
			//trace(this + ".arrangeItems(" + arguments + ")");
			//trace("visibleItemsList=" + visibleItemsList);
			
			if(lockArrangeItemsCall)
			{
				return;
			}
			
			var visibleListIndex:Number = 0;
			if(item)
			{
				visibleListIndex = ArrayHandling.getItemIndex(visibleItemsList, item);
			}
			if(!isNaN(itemIndex))
			{
				visibleListIndex = ArrayHandling.getItemIndex(visibleItemsList, itemsList[itemIndex]);
			}
			item = visibleItemsList[visibleListIndex];
			
			if(visibleListIndex<0)
			{
				if(dispatchItemsRearrangeEventWhenEmpty)
				{
					dispatchEvent(new UICompositionEvent(UICompositionEvent.ITEMS_REARRANGE, undefined, undefined, Number.NaN, dispatchBubblingEvents));
				}
				return;
			}
			
			extra = extra || new Object();
			extra = beforeArrangeItems(visibleListIndex, visibleItemsList[visibleListIndex], extra) || extra;
			
			for(var i:Number=visibleListIndex; i<visibleItemsList.length; i++)
			{
				extra = locateItem(i, visibleItemsList[i] as DisplayObject, extra) || extra;
			}
			
			//dispatchEvent(new UICompositionEvent(UICompositionEvent.ITEMS_REARRANGE, undefined, undefined, undefined, dispatchBubblingEvents));
			dispatchEvent(new UICompositionEvent(UICompositionEvent.ITEMS_REARRANGE, item ? (item as Object).dataProvider : undefined, item, item ? (item as Object).index : Number.NaN, dispatchBubblingEvents));
		}
		protected function beforeArrangeItems(itemIndex:Number = undefined, item:DisplayObject = undefined, extra:Object = undefined):*
		{
		}
		protected function locateItem(visibleListIndex:Number, itemMC:DisplayObject, extra:Object = undefined):*
		{
			//trace(this + ".locateItem(" + arguments + ")");
			
			if(visibleListIndex > 0)
			{
				itemMC.x = (visibleItemsList[visibleListIndex - 1] as DisplayObject).x + (visibleItemsList[visibleListIndex - 1] as DisplayObject).width;
			}
			else
			{
				itemMC.x = 0;
			}
		}
		//═════════════════════════════════════════════════════════════════════════════════════════════════════════════
		
	}
}